#include <curses.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <iostream>
#include <cstring>
#include <winsock2.h>
#include <fstream>
#include <time.h>
using namespace std;
struct Response
{
	std::string prefix;
	std::string command;
	std::string params;
	std::string trailer;
};

// Parse fallid fra thordi
Response parseResponse(std::string p_resp){
	Response rslt;
	if(p_resp[0] == ':'){
		int prefixEnd= p_resp.find_first_of(" ");
		rslt.prefix= p_resp.substr(1, prefixEnd -1);
		p_resp= p_resp.substr(prefixEnd + 1);
	}
	int commEnd= p_resp.find_first_of(" ");
	rslt.command= p_resp.substr(0, commEnd);
	p_resp= p_resp.substr(commEnd + 1);
	int paramsEnd= p_resp.find_first_of(":");
	rslt.params= p_resp.substr(0, paramsEnd);
	rslt.trailer= p_resp.substr(paramsEnd + 1);
    rslt.trailer = p_resp.substr(0,  p_resp.size()-1); // Klippa aftan af pakkanum, ekki alveg viss hvers vegna
	//TODO: whole packets are sometimes seen trailing..buffer size problem?
	//or add a check for the \r\n characters to last line to prevent
	return rslt;
}

WINDOW *start = initscr();
WINDOW *my_win = newwin(24, 80, 0, 0);    // Gluggi sem baedi follin hafa adgang ad
int end = endwin();
SOCKET sock;                              // Socket sem baedi follin hafa adgang ad
const int BUFFER_SIZE = 1024;

void wrtwin(char *input) {
     
    char *buff = new char[512];
    for (int i = 0; i < 24; i++) {
        wmove(my_win,i+1,0);
        winstr(my_win, buff);
        mvwaddstr(my_win, i, 0, buff);
    }
    wmove(my_win,23,0);
    wclrtoeol(my_win);
    
    waddstr(my_win, input);
	wrefresh(my_win);
}

// Fall / thread sem les gogn og skrifar i gluggann

void myThread( void* number)
{
    initscr();
	wrtwin("thread started \n");
	wrefresh(my_win);
	char recvData[BUFFER_SIZE];
	Response ble;
	string ha;
	string ha2;
	while(1)
		{
         memset(&recvData, 0, BUFFER_SIZE);
         recv(sock, recvData, BUFFER_SIZE, 0);
         ha = recvData;
         ble = parseResponse(ha);
         
         ha2 = ble.trailer;
         char *a = new char[ha2.size()+1];  // Breyta string i *char
         a[ha2.size()] = 0;
         memcpy(a, ha2.c_str(), ha2.size());
         
		 wrtwin(a);
		 
	}
	endwin();
	 _endthread();
}

int main(int argc, char *argv[])
{	
    // Sama og adur
    
    const int TCP_PORT = 6667;
    const char* IRC_SERVER = "irc.freenode.org";
    WSADATA wsaData;
    WORD version = MAKEWORD(2, 2);
    WSAStartup(version, &wsaData);

    sockaddr_in serverAddr;
    hostent *host;
    

    host = (hostent *) gethostbyname((char *) IRC_SERVER);
    sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    

    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(TCP_PORT);
    serverAddr.sin_addr = *((struct in_addr *) host->h_addr);
    memset(&(serverAddr.sin_zero), 0, 8);
    
    connect(sock, (sockaddr*) &serverAddr, sizeof(sockaddr));
    
    wrtwin("Connected to server:");  // Prenta i gluggan
    initscr();			/* Start curses mode 		*/
	cbreak();			/* Line buffering disabled, Pass on everty thing to me 		*/
	keypad(stdscr, TRUE);		/* I need that nifty F1 	*/
    string request;
	 _beginthread( myThread, 0,  NULL);   // Keyrum threadid samhlida
	
    // Til ad baeta vid "\n"
    char array1[512];
	char test[512];
    char array2[] = "\n";
          
    // Sendum thad sem tarf
	request = "CAP LS\n";
    send(sock, request.c_str(), request.length(), 0);
    request = "NICK valdi\n";
    send(sock, request.c_str(), request.length(), 0);
    request = "USER valdi valdi irc.freenode.net :Karl Valdimar Kristinsson\n";
    send(sock, request.c_str(), request.length(), 0);
    request = "CAP REQ :identify-msg\n";
    send(sock, request.c_str(), request.length(), 0);
    request = "CAP END\n";
    send(sock, request.c_str(), request.length(), 0);
    
    // Lyykja til ad lesa input og senda
    // Slata vesen i kringum ad baeta vid "\n"
    
    while (true) {
          move(24,0);
          clrtoeol();
          mvaddstr(24,0,"<valdi> ");
          getstr(test);
          
          // Baeta vid "\n"
          std::strncpy(array1, test, BUFFER_SIZE-1); //-1 for null-termination
          std::strncat(array1,array2,BUFFER_SIZE-strlen(array1)-1); //-1 for null-termination
          
          wrtwin(array1);
          send(sock, array1, strlen(array1), 0);
	      memset(&test, 0, 512);
	      memset(&array1, 0, 512);
	      refresh();
    }
	endwin();			/* End curses mode		  */
	return 0;
}
